﻿using UnityEngine;
using System.Collections;

[RequireComponent(typeof(Rigidbody))]
public class PhysicsController : MonoBehaviour
{
    public Vector3 Torque = Vector3.zero;
    public Vector3 Velocity = Vector3.zero;
    public ForceMode VelocityForceMode = ForceMode.Acceleration;
    public bool RotateBothWays = false;

    private float _timer = 1.0f;
    private bool _canMove = true;
    private ConfigurableJoint _joint;
    private KeyCode controlButton = KeyCode.A;
    private bool controllable = false;
    private bool execute = true;

    private float angleY = 0.0f;
    private float angleZ = 0.0f;

    public void Init(Vector3 velocity, Vector3 torque, float timer, float drag, float angularDrag, ForceMode velocityForceMode) 
    {
        execute = false;
        Velocity = velocity;
        _timer = timer;
        RotateBothWays = true;
        Torque = torque;
        Velocity = velocity;
        VelocityForceMode = velocityForceMode;
        rigidbody.drag = drag;
        rigidbody.angularDrag = angularDrag;

        rigidbody.useConeFriction = false;

        _joint = GetComponent<ConfigurableJoint>();

        Manager.Instance.ControllableEvent += Controllable;
        
        StartCoroutine(Timer());
        StartCoroutine(Remove());
	}

    void FixedUpdate()
    {
        if (_joint == null)
        {
            _joint = GetComponent<ConfigurableJoint>();
        }
        else
        {
            if (controllable)
            {
                if (Input.GetKeyDown(controlButton) && !execute)
                {
                    StartCoroutine(Execute());
                }
            }


            if (execute)
            {
                //Is it a bone (both locked) then return
                if (_joint.angularYMotion == ConfigurableJointMotion.Locked && _joint.angularZMotion == ConfigurableJointMotion.Locked)
                    return;

                //Handle rotation
                if (_joint.angularYMotion == ConfigurableJointMotion.Limited)
                {
                    if (Torque.y > 0 && angleY <= Torque.y)
                    {
                        transform.Rotate(Vector3.up, Torque.y * ((Time.fixedDeltaTime * 5.0f) / _timer), Space.World);
                        angleY += Torque.y * ((Time.fixedDeltaTime * 2.0f) / _timer);

                    }
                    else if (Torque.y < 0 && angleY >= Torque.y)
                    {
                        transform.Rotate(Vector3.up, Torque.y * ((Time.fixedDeltaTime * 5.0f) / _timer), Space.World);
                        angleY += Torque.y * ((Time.fixedDeltaTime * 2.0f) / _timer);
                    }
                }


                if (_joint.angularZMotion == ConfigurableJointMotion.Limited)
                {
                    if (Torque.z > 0 && angleZ <= Torque.z)
                    {
                        transform.Rotate(Vector3.forward, Torque.z * ((Time.fixedDeltaTime * 5.0f) / _timer), Space.World);
                        angleZ += Torque.z * ((Time.fixedDeltaTime * 2.0f) / _timer);

                    }
                    else if (Torque.z < 0 && angleZ >= Torque.z)
                    {
                        transform.Rotate(Vector3.forward, Torque.z * ((Time.fixedDeltaTime * 5.0f) / _timer), Space.World);
                        angleZ += Torque.z * ((Time.fixedDeltaTime * 2.0f) / _timer);
                    }
                }


                if (RotateBothWays && _canMove)
                {
                    Torque *= -1.0f;
                    StartCoroutine(Timer());
                    rigidbody.AddForce(Velocity, VelocityForceMode);
                }
            }
        }
    }

    IEnumerator Timer()
    {
        _canMove = false;
        yield return new WaitForSeconds(_timer);
        _canMove = true;
    }

    IEnumerator Remove()
    {
        yield return new WaitForSeconds(1.0f);
        
        execute = true;

        yield return new WaitForSeconds(Manager.Instance.Duration - 1.0f);

        if (Manager.Instance.State == ManagerState.Evolution)
            Destroy(gameObject);
    }

    public void Controllable(bool c)
    {
        if (c)
        {
            controllable = true;
            execute = false;
        }
        else
        {
            controllable = false;
            execute = true;
        }
    }

    IEnumerator Execute()
    {
        execute = true;
        yield return new WaitForSeconds(_timer);
        execute = false;
    }

    public void RemoveManually()
    {
        Destroy(gameObject);
    }

    public void SetKeyCode(KeyCode kc)
    {
        controlButton = kc;
    }
}
